﻿Imports Aricie.DNN.UI.Attributes
Imports System.ComponentModel
Imports Aricie.Collections
Imports Aricie.DNN.ComponentModel
Imports DotNetNuke.UI.WebControls
Imports Aricie.DNN.UI.WebControls.EditControls
Imports System.Xml.Serialization
Imports Aricie.DNN.Diagnostics

Namespace Aricie.DNN.Services.Url.FriendlyUrl
    <Serializable()> _
    Public Class ProviderUrlGroup
        Inherits VariableUrlGroup
        Implements ISelector(Of GroupParamsRewrite), ISelector(Of UrlProviderInfo)

        Private groupRewritesLock As New Object

        <NonSerialized()> _
        Private _ProviderList As SerializableDictionary(Of String, UrlProviderInfo)
        <NonSerialized()> _
        Private _UrlProvider As IUrlRewriterProvider
        <NonSerialized()> _
        Private _GroupParams As GroupParamsRewrite

        Private _UrlProviderName As String = ""

        '<IsReadOnly(True)> _
        <ExtendedCategory("MainSettings")> _
        <SortOrder(7)> _
        <Editor(GetType(SelectorEditControl), GetType(EditControl))> _
        <ProvidersSelector("DisplayName")> _
        <AutoPostBack()> _
        Public Property UrlProviderName() As String
            Get
                Return _UrlProviderName
            End Get
            Set(value As String)
                If value <> _UrlProviderName Then
                    _UrlProvider = Nothing
                    _UrlProviderName = value
                End If
            End Set
        End Property
        
       
        '<IsReadOnly(True)> _
        <ExtendedCategory("MainSettings")> _
        <SortOrder(8)> _
        <Editor(GetType(SelectorEditControl), GetType(EditControl))> _
        <ProvidersSelector("GroupName")> _
        <AutoPostBack()> _
        Public Property GroupName() As String = String.Empty

        '<Browsable(False)> _
        <ExtendedCategory("MainSettings")> _
        <SortOrder(9)> _
        Public ReadOnly Property GroupDescription() As String
            Get
                Dim toreturn As String = String.Empty
                If Me.GroupParamRewrite IsNot Nothing Then
                    toreturn = Me.GroupParamRewrite.Description
                End If
                Return toreturn
            End Get
        End Property

        <ExtendedCategory("FilterSettings")> _
        Public Overrides Property EnableFilter() As Boolean = True

        '<Browsable(False)> _
        <ExtendedCategory("TechnicalSettings")> _
        Public Overrides ReadOnly Property SupportsEntityToken() As Boolean
            Get
                If Me.GroupParamRewrite IsNot Nothing Then
                    Return Me.GroupParamRewrite.SupportsEntityToken
                End If
                Return False
            End Get
        End Property
     

        '<NonSerialized()> _
        'Private _RewritersByRewrite As Dictionary(Of GroupParamsRewrite, IUrlRewriterProvider)
        '<NonSerialized()> _
        'Private _RewritesByRewriters As Dictionary(Of IUrlRewriterProvider, List(Of GroupParamsRewrite))

        '<Browsable(False)> _
        '<XmlIgnore()> _
        'Public ReadOnly Property RewritesByRewriters() As Dictionary(Of IUrlRewriterProvider, List(Of GroupParamsRewrite))
        '    Get
        '        If _RewritesByRewriters Is Nothing Then
        '            InitUrlProvider()
        '        End If
        '        Return _RewritesByRewriters
        '    End Get
        'End Property

        '<Browsable(False)> _
        '<XmlIgnore()> _
        'Public ReadOnly Property RewritersByRewrite() As Dictionary(Of GroupParamsRewrite, IUrlRewriterProvider)
        '    Get
        '        If _RewritersByRewrite Is Nothing Then
        '            InitUrlProvider()
        '        End If
        '        Return _RewritersByRewrite
        '    End Get
        'End Property


        <Browsable(False)> _
       <XmlIgnore()> _
        Public ReadOnly Property UrlProvider() As IUrlRewriterProvider
            Get
                If _UrlProvider Is Nothing Then 'AndAlso Not String.IsNullOrEmpty(UrlProviderName) Then
                    'InitUrlProvider()
                    '_UrlProvider = FriendlierUrlConfig.Instance.AvailableUrlrewriters(UrlProviderName).GetProvider()
                    If String.IsNullOrEmpty(UrlProviderName) Then
                        UrlProviderName = FriendlierUrlConfig.Instance.AvailableUrlrewriters(GetType(StandardUrlRewriterProvider).Name).DisplayName
                    End If
                    Dim providerConfig As UrlProviderInfo = Nothing
                    If Not FriendlierUrlConfig.Instance.AvailableUrlrewriters.TryGetValue(UrlProviderName, providerConfig) Then
                        Throw New ApplicationException(String.Format("Url Provider {0} was not found in configuration", UrlProviderName))
                    End If
                    _UrlProvider = providerConfig.GetProvider()
                End If
                Return _UrlProvider
            End Get
        End Property


        Private _GroupParamRewrite As GroupParamsRewrite


        <Browsable(False)> _
        <XmlIgnore()> _
        Public ReadOnly Property GroupParamRewrite As GroupParamsRewrite
            Get
                If Me._GroupParamRewrite Is Nothing Then
                    If Me.UrlProvider IsNot Nothing Then
                        For Each rewrite As GroupParamsRewrite In Me.UrlProvider.GetRewrites()
                            If rewrite.GroupName.ToLowerInvariant = GroupName.ToLowerInvariant Then
                                Me._GroupParamRewrite = rewrite
                                Exit For
                            End If
                        Next
                    End If
                End If
                Return Me._GroupParamRewrite
            End Get
        End Property


#Region "Methods"


        'Private Sub InitUrlProvider()
        '    SyncLock groupRewritesLock
        '        _RewritersByRewrite = New Dictionary(Of GroupParamsRewrite, IUrlRewriterProvider)
        '        _RewritesByRewriters = New Dictionary(Of IUrlRewriterProvider, List(Of GroupParamsRewrite))

        '        If String.IsNullOrEmpty(UrlProviderName) Then
        '            UrlProviderName = FriendlierUrlConfig.Instance.AvailableUrlrewriters(GetType(StandardUrlRewriterProvider).Name).DisplayName
        '        End If
        '        _UrlProvider = FriendlierUrlConfig.Instance.AvailableUrlrewriters(UrlProviderName).GetProvider()
        '        Dim tmpList As List(Of GroupParamsRewrite) = _UrlProvider.GetRewrites()
        '        _RewritesByRewriters(urlProvider) = tmpList

        '        For Each newRewrite As GroupParamsRewrite In tmpList
        '            If Not _RewritersByRewrite.ContainsKey(newRewrite) Then
        '                _RewritersByRewrite(newRewrite) = _UrlProvider
        '            End If
        '        Next

        '    End SyncLock
        'End Sub

        'Private Overloads Function GetGroupRewrites(ByVal urlProvider As IUrlRewriterProvider) As SerializableDictionary(Of String, List(Of GroupParamsRewrite))
        '    Dim toReturn As New SerializableDictionary(Of String, List(Of GroupParamsRewrite))
        '    If urlProvider IsNot Nothing Then
        '        For Each newRewrite As GroupParamsRewrite In _RewritesByRewriters(urlProvider)
        '            If Not toReturn.ContainsKey(newRewrite.GroupName) Then
        '                toReturn(newRewrite.GroupName) = New List(Of GroupParamsRewrite)
        '            End If
        '            If Not toReturn(newRewrite.GroupName).Contains(newRewrite) Then
        '                toReturn(newRewrite.GroupName).Add(newRewrite)
        '            End If
        '        Next
        '    End If
        '    Return toReturn
        'End Function

        Public Function GetSelector(ByVal propertyName As String) As System.Collections.IList Implements ComponentModel.ISelector.GetSelector
            Select Case propertyName
                Case "UrlProviderName"
                    Return DirectCast(GetSelectorG1(propertyName), IList)
                Case "GroupName"
                    Return DirectCast(GetSelectorG(propertyName), IList)
                Case Else
                    Return Nothing
            End Select

        End Function

        Public Function GetSelectorG(ByVal propertyName As String) As System.Collections.Generic.IList(Of GroupParamsRewrite) Implements ComponentModel.ISelector(Of GroupParamsRewrite).GetSelectorG
            Select Case propertyName
                Case "GroupName"

                    'Dim toReturn As New List(Of GroupParamsRewrite)
                    Dim toReturn As List(Of GroupParamsRewrite) = Me.UrlProvider.GetRewrites()
                    'InitUrlProvider()
                    'If Not String.IsNullOrEmpty(UrlProviderName) Then
                    '    For Each entry As KeyValuePair(Of String, List(Of GroupParamsRewrite)) In GetGroupRewrites(FriendlierUrlConfig.Instance.AvailableUrlrewriters(UrlProviderName).GetProvider)
                    '        toReturn.AddRange(entry.Value)
                    '    Next
                    'End If

                    Return toReturn
                Case Else
                    Return Nothing
            End Select

        End Function

        Public Function GetSelectorG1(ByVal propertyName As String) As System.Collections.Generic.IList(Of UrlProviderInfo) Implements ComponentModel.ISelector(Of UrlProviderInfo).GetSelectorG
            Select Case propertyName
                Case "UrlProviderName"
                    Dim toReturn As New List(Of UrlProviderInfo)
                    For Each item As UrlProviderInfo In FriendlierUrlConfig.Instance.AvailableUrlrewriters.Values
                        toReturn.Add(item)
                    Next
                    Return toReturn
                Case Else
                    Return Nothing
            End Select
        End Function

        Protected Overrides Function GetRawVariable(ByVal writer As UrlRewriteContext) As GroupRewriteResult
            'Dim toReturn As New GroupRewriteResult
            'Dim targetList As List(Of GroupParamsRewrite) = Nothing
            'If RewritesByRewriters.TryGetValue(Me.UrlProvider, targetList) Then
            '    For Each paramsRewrite As GroupParamsRewrite In targetList
            '        If String.Compare(paramsRewrite.GroupName, GroupName, StringComparison.OrdinalIgnoreCase) = 0 Then
            '            toReturn = Me.RewriteProviderUrlGroup(writer, paramsRewrite, GroupName)
            '        End If
            '    Next
            'Else
            '    Dim appException As New ApplicationException("Missing rewriter for group " & Me.GroupName & " & UrlProvider " & Me.UrlProviderName)
            '    Throw appException
            'End If
            'Return toReturn
            Return Me.RewriteProviderUrlGroup(writer, Me.GroupParamRewrite) ', Me.GroupParamRewrite.GroupName)
        End Function

        'Private Function RewriteProviderUrlGroup(ByVal writer As UrlRewriteContext, ByVal paramsRewrite As GroupParamsRewrite, ByVal groupName As String) As GroupRewriteResult
        Private Function RewriteProviderUrlGroup(ByVal writer As UrlRewriteContext, ByVal paramsRewrite As GroupParamsRewrite) As GroupRewriteResult


            Dim rewriteParams As New Dictionary(Of UrlParam, String)
            Dim mandatoryParamMissing As Boolean = False
            For Each param As UrlParam In paramsRewrite.UrlParams.Keys

                Select Case param
                    Case UrlParam.DNNParams
                        For Each objParam As KeyValuePair(Of UrlParam, String) In writer.RewriteInput.DnnParams
                            If (writer.ParamsUsage(objParam.Key) = ParamState.Untouched) Then
                                rewriteParams.Add(objParam.Key, objParam.Value)
                            End If
                        Next
                    Case UrlParam.QueryString
                        For Each objParam As KeyValuePair(Of UrlParam, String) In writer.RewriteInput.QueryStringValues
                            If (writer.ParamsUsage(objParam.Key) = ParamState.Untouched) Then
                                rewriteParams.Add(objParam.Key, objParam.Value)
                            End If
                        Next
                    Case Else
                        Dim paramValue As String = Nothing
                        If writer.RewriteInput.Params.TryGetValue(param, paramValue) _
                                AndAlso (writer.ParamsUsage(param) = ParamState.Untouched _
                                         OrElse (writer.ParamsUsage(param) = ParamState.Used _
                                                 AndAlso (paramsRewrite.UrlParams(param) And ParamNature.Mandatory) = ParamNature.Mandatory)) Then
                            rewriteParams(param) = paramValue
                        ElseIf (paramsRewrite.UrlParams(param) And ParamNature.Mandatory) = ParamNature.Mandatory Then
                            mandatoryParamMissing = True
                            If FriendlierUrlConfig.Instance.LogMissingMandatory Then
                                Dim objPair As New KeyValuePair(Of String, String)("Parameter Name", param.SyntaxOptions(0))
                                Dim objPair2 As New KeyValuePair(Of String, String)("Rewrite Rule", writer.RewriteInput.Strategy.FriendlyRule.ToString())
                                Dim objPair3 As New KeyValuePair(Of String, String)("Original Url", writer.RewriteInput.Url)
                                Dim objDebug As New DebugInfo(Debug.DebugType, Debug.Labels.MissingMandatoryParameter, objPair, objPair2, objPair3)

                                SimpleDebugLogger.Instance.AddDebugInfo(objDebug)

                            End If
                        End If

                End Select

            Next
            Dim toReturn As New GroupRewriteResult
            If paramsRewrite.Localized Then
                If Not rewriteParams.ContainsKey(UrlParam.Language) Then
                    Dim paramValue As String = Nothing
                    writer.RewriteInput.Params.TryGetValue(UrlParam.Language, paramValue)
                    rewriteParams(UrlParam.Language) = paramValue
                End If
            End If

            If Not mandatoryParamMissing Then
                'Dim rewriter As IUrlRewriterProvider = Me.RewritersByRewrite(paramsRewrite)
                If Me.RewriteType = RewriteType.None Then
                    For Each objParam As UrlParam In rewriteParams.Keys
                        toReturn.ConsumedParameters(objParam) = True
                    Next
                Else
                    ' ajout de la gestion de simpleAPI
                    Dim objISimpleApi As SimpleAPI.ISimpleRewritingGroup = TryCast(paramsRewrite, SimpleAPI.ISimpleRewritingGroup)
                    If objISimpleApi IsNot Nothing Then
                        ' notre GroupParamsRewrite prend en charge la transformation
                        toReturn = objISimpleApi.Rewrite(Me.RewriteType, rewriteParams, writer.RewriteInput.Strategy)
                    Else
                        ' il ne prend pas en charge la transformation, on passe dans le provider
                        'toReturn = rewriter.RewriteParams(groupName, Me.RewriteType, rewriteParams, writer.RewriteInput.Strategy)
                        toReturn = Me.UrlProvider.RewriteParams(Me.GroupParamRewrite.GroupName, Me.RewriteType, rewriteParams, writer.RewriteInput.Strategy)
                    End If
                    ' fin de la modification de gestion de simpleAPI
                End If

                If (toReturn.HasContent) OrElse Me.RewriteType = RewriteType.None Then
                    Dim tempNature As ParamNature
                    For Each consumedParam As KeyValuePair(Of UrlParam, Boolean) In toReturn.ConsumedParameters
                        If consumedParam.Value Then
                            If paramsRewrite.UrlParams.TryGetValue(consumedParam.Key, tempNature) _
                                    AndAlso ((tempNature And ParamNature.Exclusive) = ParamNature.Exclusive) Then
                                writer.ParamsUsage(consumedParam.Key) = ParamState.UsedAndLocked
                            Else
                                writer.ParamsUsage(consumedParam.Key) = ParamState.Used
                            End If
                        End If
                    Next
                End If
            End If
            Return toReturn

        End Function

        Protected Overrides Function GetName() As String
            Return Me.GroupName.ToString()
        End Function


#End Region





        Private Class ProviderNamesInnerAttributes
            Implements IAttributesProvider


            Public Function GetAttributes() As System.Collections.Generic.IEnumerable(Of System.Attribute) Implements DNN.UI.Attributes.IAttributesProvider.GetAttributes
                Return New Attribute() {New SelectorAttribute(GetType(UrlProviderSelector), "Name", "Name", True, False, "", "", False, False)}
            End Function
        End Class





    End Class
End Namespace
